﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using TaxonomyReader;
using System.Collections;
using System.Text.RegularExpressions;
using System.IO;

namespace TaxonomyReader
{
    public class TaxonomyManager
    {
        //this variable will be used through out application
        public static XsdBO MAINXSD;

        public static Hashtable EXTENDEDTYPES;

        string m_xsdFileName = null;

        //remove any ../ or http:// references to get only xsd file name
        string GetXsdName(string xsdName)
        {
            string reqXsd = "";
            if (xsdName.Contains("http://"))
            {
                string[] spl2 = xsdName.Split('/');
                reqXsd = spl2[spl2.Length - 1];
            }
            else
            {
                if (xsdName.Contains('/'))
                {
                    xsdName = xsdName.Replace('/', '\\');
                }

                string[] spl2 = xsdName.Split('\\');
                reqXsd = spl2[spl2.Length - 1];
            }

            return reqXsd;
        }

        public ElementBO GetElementByHref(string href)
        {
            string[] spl1 = href.Split('#');
            string xsdName = spl1[0];
            m_xsdFileName = GetXsdName(xsdName);
            string elementId = spl1[1];

            XsdBO xsd1 = GetXsdBOByXsdName(MAINXSD);

            //the href is not imported
            if (xsd1 == null)
                return null;

            ElementBO ele = xsd1.Elements.Find(p => p.Id == elementId);

            ////foreach problem
            //if (ele.Id == "ifrs_DisclosureOfChangesInAccountingPoliciesAccountingEstimatesAndErrorsExplanatory")
            //{

            //}

            return ele;
        }

        //public PresentationBO GetPresentationByHref(string href, string presLinkHref)
        //{
        //    string[] spl1 = href.Split('#');
        //    string xsdFileName = spl1[0];
        //    m_xsdFileName = GetXsdName(xsdFileName);
        //    m_GetPrBo = null;
        //    m_PresRef = presLinkHref;
        //    m_href = href;

        //    FindInImports(MAINXSD);

        //    return m_GetPrBo;
        //}

        //PresentationBO m_GetPrBo = null;
        //string m_PresRef = null;
        //string m_href = null;
        

        //void FindInImports(XsdBO xsd)
        //{
        //    if (xsd.XsdName == m_xsdFileName)
        //    {
        //        if (xsd.PresLink == null)
        //            return;

        //        foreach (PresentationLinkBO prLink in mainXsd.PresLink[0].PresentationLinks)
        //        {
        //            if (prLink.Href == m_PresRef)
        //            {
        //                foreach (PresentationBO prbo in prLink.Presentations)
        //                {
        //                    FindPresentationBORec(prbo);
        //                    if (m_GetPrBo != null)
        //                        return;
        //                }
        //            }
        //        }
        //    }
        //    else
        //    {
        //        if (xsd.ImportedXsds == null)
        //            return;
        //        foreach (XsdBO xsd1 in xsd.ImportedXsds)
        //        {
        //            FindInImports(xsd1);
        //            if (m_GetPrBo != null)
        //                return;
        //        }
        //    }
        //}

        //void FindPresentationBORec(PresentationBO prbo)
        //{
        //    if (prbo.Element_Href == m_PresRef)
        //    {
        //        m_GetPrBo = prbo;
        //        return;
        //    }

        //    if (prbo.Children == null)
        //        return;

        //    foreach (PresentationBO prbo1 in prbo.Children)
        //    {
        //        FindPresentationBORec(prbo1);
        //    }
        //}
        
        public List<string> ValidateAllTaxonomies()
        {
            List<string> errorList = new List<string>();

            return errorList;
        }

        //compares xsd object and its imports with m_xsdfilename and returns matching xsd object
        private XsdBO GetXsdBOByXsdName(XsdBO xsd)
        {
            if (xsd.XsdName == m_xsdFileName)
                return xsd;

            if (xsd.ImportedXsds == null)
                return null;

            foreach (XsdBO xsd1 in xsd.ImportedXsds)
            {
                XsdBO xsdF = GetXsdBOByXsdName(xsd1);
                if (xsdF != null)
                    return xsdF;
            }

            return null;
        }

        public static XsdBO FindXsd(string xsdName, XsdBO xsd1)
        {
            if (xsd1.XsdName == xsdName)
                return xsd1;

            if(xsd1.ImportedXsds != null)
                foreach (XsdBO xsd2 in xsd1.ImportedXsds)
                {
                    XsdBO xsd3 = FindXsd(xsdName, xsd2);
                    if (xsd3 != null)
                        return xsd3;
                }

            return null;
        }

        public List<string> GetImportedXsdNames(string xsdName)
        {
            List<string> retVal = new List<string>();
            m_xsdFileName = xsdName;
            XsdBO xsd = GetXsdBOByXsdName(MAINXSD);

            if (xsd == null)
                return null;

            if (xsd.ImportedXsds == null)
                return null;

            foreach (XsdBO xsd1 in xsd.ImportedXsds)
            {
                retVal.Add(xsd1.XsdName);
            }

            return retVal;
        }

        public List<PresentationLinkbaseBO> GetPresentationLinkbaseForXsd(string xsdName)
        {
            m_xsdFileName = xsdName;
            XsdBO xsd1 = GetXsdBOByXsdName(MAINXSD);

            if (xsd1 == null)
                return null;

            return xsd1.PresLink;
        }

        public List<CalculationLinkbaseBO> GetCalculationLinkbaseForXsd(string xsdName)
        {
            m_xsdFileName = xsdName;
            XsdBO xsd1 = GetXsdBOByXsdName(MAINXSD);

            if (xsd1 == null)
                return null;

            return xsd1.CalcLink;
        }

        public List<DefinitonLinkbaseBO> GetDefinitionLinkbaseForXsd(string xsdName)
        {
            m_xsdFileName = xsdName;
            XsdBO xsd1 = GetXsdBOByXsdName(MAINXSD);

            if (xsd1 == null)
                return null;

            return xsd1.DefLink;
        }

        //#region Merge Linkbases ?/
        //public void MergeDuplicateLinkbasesToBase(XsdBO xsd)
        //{
        //    foreach (PresentationLinkbaseBO prlnBasBo in xsd.PresLink)
        //    {
        //        foreach (PresentationLinkBO prlnBo in prlnBasBo.PresentationLinks)
        //        {
        //            string[] prHref = prlnBo.Href.Split('#');
        //            if (prHref[0] != xsd.XsdName)
        //            {
        //                //search for href xsd in imported taxonomies
        //                XsdBO xsd1 = GetXsdBOByXsdName(xsd, prHref[0]);
        //                if (xsd1 != null)
        //                {
                            
        //                }
        //            }
        //        }
        //    }
        //}
        //#endregion


        public XsdBO GetXsdBOByXsdName(XsdBO root, string xsdName)
        {
            if (root.XsdName == xsdName)
                return root;

            else if (root.ImportedXsds != null)
            {
                foreach (XsdBO xsd1 in root.ImportedXsds)
                {
                    XsdBO retval = GetXsdBOByXsdName(xsd1, xsdName);
                    if (retval != null)
                        return retval;
                }
            }

            return null;
        }

        public void SetSchemaElementsBaseTypes(ref XsdBO mainXsd)
        {
            SerializeDeserialize srDr = new SerializeDeserialize();

            object obj = srDr.Deserialize(mainXsd.XsdName + "_cmpxtyp");
            if (obj != null)
            {
                mainXsd = null;
                mainXsd = obj as XsdBO;
                
                //the foreach problem
                //if(mainXsd.Elements != null)
                //{
                //    ElementBO elbo = mainXsd.Elements.Find(p => p.Id== "ifrs_DisclosureOfChangesInAccountingPoliciesAccountingEstimatesAndErrorsExplanatory");

                //    if (elbo != null)
                //    {

                //    }
                //}
            }
            else
            {
                if (mainXsd.Elements != null)
                {
                    foreach (ElementBO element in mainXsd.Elements)
                    {
                        if (element.Type_str != null && element.Type_str != "")
                        {
                            restrictionStr = "";
                            string[] spl = Regex.Split(element.Type_str, ":::");
                            XsdType type = FindComplexType(spl[0].Split(':')[1], spl[1]);
                            element.Type = type;
                            element.DefinedType = spl[0];
                            element.Type_str = restrictionStr;
                        }
                    }
                    srDr.Serialize(mainXsd.XsdName + "_cmpxtyp", mainXsd);
                }
            }

            if (mainXsd.ImportedXsds != null)
            {
                //foreach will never f***ing pass the reference
                //foreach (XsdBO xsd2 in mainXsd.ImportedXsds)
                //{
                //    SetSchemaElementsBaseTypes(xsd2);
                //}

                for (int a = 0; a < mainXsd.ImportedXsds.Count; a++)
                {
                    XsdBO xsd1 = mainXsd.ImportedXsds[a];
                    SetSchemaElementsBaseTypes(ref xsd1);
                    mainXsd.ImportedXsds[a] = xsd1;
                }

            }
        }
        string restrictionStr = "";
        private XsdType FindComplexType(string typeName, string targetNamespace)
        {
            XsdBO xsd1 = GetXsdBOByTargetNamespace(MAINXSD, targetNamespace);

            if (xsd1 == null || xsd1.ComplexTypes == null)
                return XsdType.stringItemType;

            foreach (ComplexType cpxTyp in xsd1.ComplexTypes)
            {
                if (cpxTyp.name == typeName)
                {
                    try
                    {
                        if (cpxTyp.baseType.Contains("xbrli:"))
                        {
                            restrictionStr = cpxTyp.restriction;
                            XsdType retVal = (XsdType)Enum.Parse(typeof(XsdType), cpxTyp.baseType.Replace("xbrli:", ""));
                            return retVal;
                        }
                        else
                        {
                            string[] splTypes = cpxTyp.baseType.Split(':');
                            //get namespace from current xsd and find the type
                            string tNs = xsd1.Namespaces.Find(p => p.Contains(splTypes[0]));
                            if (tNs != null && tNs != "")
                            {
                                tNs = tNs.Split(':')[1];
                                XsdType type1 = FindComplexType(splTypes[1], tNs);
                                return type1;
                            }
                        }
                    }
                    catch
                    {
                        return XsdType.stringItemType;
                    }
                }
            }

            return XsdType.stringItemType;
        }

        private XsdBO GetXsdBOByTargetNamespace(XsdBO mainXsd, string targetNamespace)
        {
            if (mainXsd.targetNamespace == targetNamespace)
                return mainXsd;

            if(mainXsd.ImportedXsds != null)
                foreach (XsdBO xsd1 in mainXsd.ImportedXsds)
                {
                    XsdBO xsdRet = GetXsdBOByTargetNamespace(xsd1, targetNamespace);
                    if (xsdRet != null)
                        return xsdRet;
                }

            return null;
        }



        #region Preferred Labels

        /// <summary>
        /// set labels for the presentation elements based on preferred label attribute
        /// </summary>
        /// <param name="xsd">the input taxonomy object</param>
        /// <param name="fillImports">true to set labels for presentation elements of imported taxonomy</param>
        /// <param name="useSerialized">true to serialize updated object, not recommended if the imports are different in which case different set of labels will be found</param>
        public void FillPreferredLabels(ref XsdBO xsd, bool fillImports, bool useSerialized)
        {
            try
            {
                if (xsd.PresLink != null)
                {
                    for (int a = 0; a < xsd.PresLink.Count; a++)
                    {
                        PresentationLinkbaseBO prlLinBasBO = xsd.PresLink[a];

                        string filename = prlLinBasBO.Href + "_prefLab";

                        if (useSerialized)
                        {
                            SerializeDeserialize m_srDr = new SerializeDeserialize();
                            object obj = m_srDr.Deserialize(filename);

                            if (obj != null)
                            {
                                PresentationLinkbaseBO retVal = obj as PresentationLinkbaseBO;
                                if (retVal != null)
                                {
                                    xsd.PresLink[a] = retVal;
                                    //prlLinBasBO = retVal;
                                    continue;
                                }
                            }
                        }

                        foreach (PresentationLinkBO prLnBo in prlLinBasBO.PresentationLinks)
                        {
                            foreach (PresentationBO prbo in prLnBo.Presentations)
                            {
                                m_presXsd = xsd;
                                FillPresentationElement(prbo);
                                LoadPresentationLabel(prbo);

                                #region _c
                                //////if (xsd.LabLink != null)
                                //////{
                                //////    List<LabelBO> labels = xsd.LabLink.Labels.FindAll(p => p.Href.Split('#')[1] == elementId);
                                //////    if (labels != null)
                                //////    {
                                //////        LabelBO labBo = labels.Find(p => p.LabelRole == prbo.PreferredLabel);
                                //////        if (labBo != null)
                                //////            label = labBo.Label;
                                //////        //else label is defined with different labelrole in this linkbase.
                                //////        //go to base linkbase for for getting labelrole
                                //////    }
                                //////}

                                //////if (label == "")
                                //////{
                                //////    ////WRONG
                                //////    //search for this label in basexsd
                                //////    //basexsd must be imported at lower level from this xsd,
                                //////    //so not starting from MAINXSD
                                //////    m_xsdFileName = baseXsd;
                                //////    XsdBO xsd1 = GetXsdBOByXsdName(xsd);
                                //////    if (xsd1 == null)
                                //////    {
                                //////        if (xsd.XsdErrors.UndefinedLabels == null)
                                //////            xsd.XsdErrors.UndefinedLabels = new List<string>();

                                //////        xsd.XsdErrors.UndefinedLabels.Add("Cannot find base taxonomy '" + baseXsd
                                //////            + "' for element '" + prbo.Element_Href + "' in Xsd '" + xsd.XsdName + "'");
                                //////    }
                                //////    else
                                //////    {
                                //////        if (xsd.LabLink != null)
                                //////        {
                                //////            List<LabelBO> labels = xsd1.LabLink.Labels.FindAll(p => p.Href.Split('#')[1] == elementId);
                                //////            if (labels != null)
                                //////            {
                                //////                LabelBO labBo = labels.Find(p => p.LabelRole == prbo.PreferredLabel);
                                //////                if (labBo != null)
                                //////                    label = labBo.Label;
                                //////                //else error
                                //////                else
                                //////                {
                                //////                    if (xsd.XsdErrors.UndefinedLabels == null)
                                //////                        xsd.XsdErrors.UndefinedLabels = new List<string>();

                                //////                    xsd.XsdErrors.UndefinedLabels.Add("LabelRole '" + prbo.PreferredLabel.ToDescriptionString()
                                //////                        + "' is undefined for element '" + prbo.Element_Href + "' in Xsd '" + xsd.XsdName + "' or baseXsd '" + xsd1.XsdName + "'");
                                //////                }
                                //////            }
                                //////        }
                                //////    }
                                //////}
                                #endregion
                            }
                        }

                        //will not serialize presentation-linkbases for the preferred-labels
                        //as the imports can be different in which labels will be found ?

                        ////Serialize presentation linkbase with filled labels
                        if (useSerialized)
                        {
                            SerializeDeserialize m_srDr = new SerializeDeserialize();
                            m_srDr.Serialize(prlLinBasBO.LinkBaseName+"_prefLab", prlLinBasBO);
                        }
                    }

                }

                if (!fillImports)
                    return;

                if (xsd.ImportedXsds != null)
                {
                    //f***ing references
                    for (int a = 0; a < xsd.ImportedXsds.Count;a++ )
                    {
                        XsdBO xsd1 = xsd.ImportedXsds[a];
                        FillPreferredLabels(ref xsd1, fillImports, useSerialized);
                        xsd.ImportedXsds[a] = xsd1;
                    }
                }
            }
            catch (Exception ex)
            {

            }
        }

        XsdBO m_presXsd = null;

        private void LoadPresentationLabel(PresentationBO prbo)
        {
            string[] spl = prbo.Element_Href.Split('#');
            string baseXsd = spl[0];
            string elementId = spl[1];

            //if (spl[0].Contains('/'))
            //{
            //    string[] spl1 = spl[0].Split('/');
            //    spl[0] = spl1[spl1.Length - 1];
            //}
            //m_eleHref = spl[0] + '#' + spl[1];
            m_eleHref = prbo.Element_Href;
            m_LabRole = prbo.PreferredLabelRole;

            m_prohibitedLabelIds = new List<string>();
            m_Labels = new List<LabelBO>();
            FindLabelsForLabelRole(m_presXsd);

            #region _c
            //if (label == string.Empty)
            //{
            //    if (m_presXsd.XsdErrors == null)
            //        m_presXsd.XsdErrors = new XsdError();

            //    if (m_presXsd.XsdErrors.UndefinedLabels == null)
            //        m_presXsd.XsdErrors.UndefinedLabels = new List<string>();

            //    m_presXsd.XsdErrors.UndefinedLabels.Add("LabelRole '" + prbo.PreferredLabel.ToDescriptionString()
            //        + "' is undefined for element '" + prbo.Element_Href + "'");
            //}
            #endregion

            m_Labels = m_Labels.Distinct().ToList<LabelBO>();
            prbo.PresentationLabel = m_Labels;
 
                foreach (LabelBO lab1 in prbo.PresentationLabel)
                {
                    if (lab1.LabelRole == prbo.PreferredLabelRole)
                    {
                        prbo.PreferredLabel = lab1.Label;
                        break;
                    }
                }
           
 
            if (prbo.Children != null)
            {
                foreach (PresentationBO prbo1 in prbo.Children)
                {
                    LoadPresentationLabel(prbo1);
                }
            }
        }

        string m_eleHref;
        string m_LabRole;
        List<LabelBO> m_Labels;
        List<string> m_prohibitedLabelIds;

        private void FindLabelsForLabelRole(XsdBO xsd)
        {
            if (xsd.LabLink != null)
            {
                foreach (LabelLinkbaseBO labLink in xsd.LabLink)
                {
                    List<LabelBO> labels = labLink.Labels.FindAll(p => GetXsdName(p.Href) == m_eleHref);
                    if (labels != null && labels.Count > 0)
                    {
                        foreach (LabelBO l1 in labels)
                        {
                            if (l1.Use == ArcUse.prohibit)
                            {
                                m_prohibitedLabelIds.Add(l1.LabelId);
                            }

                            if (m_prohibitedLabelIds.Contains(l1.LabelId))
                            {
                                //this is a prohibited label
                                continue;
                            }

                            //add unique labels only
                            if (m_Labels.Find(p => p.Href == l1.Href && p.LabelRole == l1.LabelRole) == null)
                            {
                                m_Labels.Add(l1);
                            }
                        }
                    }

                    #region _c
                    //labels = labLink.Labels.FindAll(p => GetXsdName(p.Href) == m_eleHref 
                    //    && p.LabelRole == m_LabRole);
                    //if (labels != null && labels.Count > 0)
                    //{
                    //    if (labels.Count > 1)
                    //    {

                    //    }

                    //    //else label is defined with different labelrole in this linkbase.
                    //    //go to imported linkbase for for getting labelrole
                    //}
                    #endregion
                }
            }

            if (xsd.ImportedXsds != null)
            {
                foreach(XsdBO xsd1 in xsd.ImportedXsds)
                {
                    FindLabelsForLabelRole(xsd1);
                }
            }
        }

        /// <summary>
        /// Fill schema details for the presentation, calculation, definition linkbase elements 
        /// </summary>
        /// <param name="xsd">the input taxonomy object</param>
        /// <param name="fillImports">true to fill schema details for linkbase of imported taxonomy</param>
        //public void FillElementDetails(XsdBO xsd, bool fillImports)
        //{
        //    try
        //    {
        //        if (xsd.PresLink != null)
        //        {
        //            foreach (PresentationLinkbaseBO prlLinBasBO in xsd.PresLink)
        //            {
        //                foreach (PresentationLinkBO prLnBo in prlLinBasBO.PresentationLinks)
        //                {
        //                    foreach (PresentationBO prbo in prLnBo.Presentations)
        //                    {
        //                        FillPresentationElement(prbo);
        //                    }
        //                }
        //                #region _c
        //                //will not serialize presentation-linkbases for the preferred-labels
        //                //as the imports can be different in which labels will be found ?

        //                ////Serialize presentation linkbase with filled labels
        //                //if (serializeUpdate)
        //                //{
        //                //    SerializeDeserialize m_srDr = new SerializeDeserialize();
        //                //    m_srDr.Serialize(prlLinBasBO.LinkBaseName, prlLinBasBO);
        //                //}
        //                #endregion
        //            }
        //        }

        //        if (!fillImports)
        //            return;

        //        if (xsd.ImportedXsds != null)
        //        {
        //            foreach (XsdBO xsd1 in xsd.ImportedXsds)
        //                FillElementDetails(xsd1, fillImports);
        //        }
        //    }
        //    catch (Exception ex)
        //    {

        //    }
        //}

        private void FillPresentationElement(PresentationBO prbo)
        {
            //if (prbo.Element_Href == "ifrs-cor_2010-02-15_ed.xsd#ifrs_BasicEarningsLossPerShareFromContinuingOperations")
            //{

            //}

            prbo.TaxonomyElement = GetElementByHref(prbo.Element_Href);

            if (prbo.Children != null)
                foreach (PresentationBO pr1 in prbo.Children)
                    FillPresentationElement(pr1);
        }

        #endregion

        #region get dynamic members for dimension

        public List<string> GetDynamicMembersForDimension(string ele_href, string link_href)
        {
            if (TaxonomyManager.MAINXSD.PresLink == null || TaxonomyManager.MAINXSD.PresLink.Count == 0)
                return null;

            m_tempDomainList = new List<string>();
            foreach (PresentationLinkBO prLink in TaxonomyManager.MAINXSD.PresLink[0].PresentationLinks)
            {
                if (prLink.Href == link_href)
                {
                    foreach (PresentationBO prbo in prLink.Presentations)
                    {
                        if (m_tempDomainList.Count > 0)
                            break;
                        SetTempDomainList(ele_href, prbo);
                    }
                }

                if (m_tempDomainList.Count > 0)
                    break;
            }

            //need to replace ',' with space 
            for (int x = 0; x < m_tempDomainList.Count;x++)
            {
                if (Regex.Split(m_tempDomainList[x],":::")[1].Contains(','))
                {
                    string[] spl123 = Regex.Split(m_tempDomainList[x], ":::");
                    spl123[1] = spl123[1].Replace(',', ' ');
                    m_tempDomainList[x] = string.Join(":::",spl123);
                }
            }

            return m_tempDomainList;
        }

        List<string> m_tempDomainList = new List<string>();

        private void SetTempDomainList(string ele_href, PresentationBO prbo)
        {
            if (prbo.Element_Href == ele_href)
            {
                //find domain
                //foreach domain-group
                foreach (PresentationBO prbo1 in prbo.Children)
                {
                    AddAllDomains(prbo1);
                }
            }
            else
            {
                if (prbo.Children != null)
                {
                    foreach (PresentationBO pr in prbo.Children)
                    {
                        if (m_tempDomainList.Count > 0)
                            break;
                        SetTempDomainList(ele_href, pr);
                    }
                }
            }

        }

        private void AddAllDomains(PresentationBO prbo1)
        {
            if (prbo1.Children != null)
            {
                foreach (PresentationBO prbo in prbo1.Children)
                {
                    m_tempDomainList.Add(prbo.Element_Href + ":::" + prbo.PreferredLabel);
                    if (prbo.Children != null)
                        AddAllDomains(prbo);
                }
            }
        }

        #endregion

        public string GetPreferredLabel(PresentationBO prbo)
        {
            foreach (LabelBO lab in prbo.PresentationLabel)
            {
                if (lab.LabelRole == prbo.PreferredLabelRole)
                    return lab.Label;
            }

            return null;
        }

        public bool IsDirectParentChild(string linkRef, string parent, string child)
        {
            foreach (PresentationLinkbaseBO prlnkbo in TaxonomyManager.MAINXSD.PresLink)
            {
                foreach (PresentationLinkBO prlnbo in prlnkbo.PresentationLinks)
                {
                    if (prlnbo.Href == linkRef)
                    {
                        foreach (PresentationBO prbo in prlnbo.Presentations)
                        {
                            return IsDirectParentChildRecursive(prbo, parent, child);
                            
                        }
                    }
                }
            }

            return false;
        }

        private bool IsDirectParentChildRecursive(PresentationBO prbo, string parent, string child)
        {
            if (prbo.Element_Href == parent)
            {
                if (prbo.Children != null)
                    foreach (PresentationBO prboChild in prbo.Children)
                    {
                        //searching only direct children..
                        if (prboChild.Element_Href == child)
                            return true;

                        //if want to search for internal children, start a recursive loop from here
                    }

                return false;
            }
            else
            {
                if(prbo.Children != null)
                    foreach (PresentationBO prbo1 in prbo.Children)
                    {
                        bool a = IsDirectParentChildRecursive(prbo1, parent, child);
                        if(a)
                            return a;
                    }
            }

            return false;
        }

        List<string> presParents = null;

        public List<string> GetAllPresParents(string link_href, string ele_href)
        {
            presParents = new List<string>();
            foreach (PresentationLinkbaseBO linkbase in TaxonomyManager.MAINXSD.PresLink)
            {
                foreach (PresentationLinkBO linkbo in linkbase.PresentationLinks)
                {
                    if (link_href == linkbo.Href)
                    {
                        foreach (PresentationBO prbo in linkbo.Presentations)
                        {
                            if (prbo.Element_Href == ele_href)
                            {
                                return null;
                            }
                            else
                            {
                                //FindPresObj(prbo,ele_href);
                            }
                        }
                    }
                }
            }
            return null;
        }

        public bool IsDirectChildParent(string linkRef, string child, string parent)
        {
            foreach (PresentationLinkbaseBO prlnkbo in TaxonomyManager.MAINXSD.PresLink)
            {
                foreach (PresentationLinkBO prlnbo in prlnkbo.PresentationLinks)
                {
                    if (prlnbo.Href == linkRef)
                    {
                        //these are root presentations
                        foreach (PresentationBO prbo in prlnbo.Presentations)
                        {
                            return IsDirectChildParentRecursive(prbo, child, parent);
                        }
                    }
                }
            }

            return false;
        }

        private bool IsDirectChildParentRecursive(PresentationBO prbo, string child, string parent)
        {
            if (prbo.Element_Href == parent)
            {
                if (prbo.Children != null)
                    foreach (PresentationBO prboChild in prbo.Children)
                    {
                        //searching only direct children..
                        if (prboChild.Element_Href == child)
                            return true;

                        //if want to search for internal children, start a recursive loop from here
                    }

                return false;
            }
            else
            {
                if (prbo.Children != null)
                    foreach (PresentationBO prbo1 in prbo.Children)
                    {
                        bool a = IsDirectChildParentRecursive(prbo1, child, parent);
                        if (a)
                            return a;
                    }
            }

            return false;
        }


        public double GetOrderForPresentationElement(string link_href, string presEl_Href)
        {
            //this is for mainxsd presentation link only
            foreach (PresentationLinkbaseBO linkbase in TaxonomyManager.MAINXSD.PresLink)
            {
                foreach (PresentationLinkBO prlnbo in linkbase.PresentationLinks)
                {
                    if (prlnbo.Href == link_href)
                    {
                        foreach(PresentationBO prbo in prlnbo.Presentations)
                        {
                            PresentationBO prbo1 = FindPresentationElementRecursive(prbo, presEl_Href);

                            if (prbo1 != null)
                            {
                                return prbo1.Order;
                            }
                        }
                    }
                }
            }

            return 0;
        }

        private PresentationBO FindPresentationElementRecursive(PresentationBO prbo, string presEl_Href)
        {
            if (prbo.Element_Href == presEl_Href)
                return prbo;

            if(prbo.Children != null)
                foreach (PresentationBO prbo1 in prbo.Children)
                {
                    PresentationBO ret = FindPresentationElementRecursive(prbo1, presEl_Href);
                    if (ret != null)
                        return ret;
                }

            return null;
        }

        
        public bool CheckDomainElement(string ele_href, string link_href)
        {
            foreach (PresentationLinkbaseBO prLnBasBo in TaxonomyManager.MAINXSD.PresLink)
            {
                foreach (PresentationLinkBO prLnBo in prLnBasBo.PresentationLinks)
                {
                    if (link_href == ele_href)
                    {
                        foreach (PresentationBO prbo in prLnBo.Presentations)
                        {
                            bool retval = CheckDomainElementRecursive(prbo, ele_href);
                            if (retval)
                                return true;
                        }
                    }
                }
            }

            return false;
        }

        bool CheckDomainElementRecursive(PresentationBO presBo, string ele_href)
        {
            if (presBo.Element_Href == ele_href)
                return false;

            if (presBo.Children != null)
            {
                foreach (PresentationBO child in presBo.Children)
                {
                    if (child.TaxonomyElement.SubstitutionGroup == XsdSubstitutionGroup.dimensionItem)
                    {
                        bool isParentDimension = FindDimensionChild(child, ele_href);
                        if (isParentDimension)
                            return true;
                    }
                    else
                    {
                        bool retval = CheckDomainElementRecursive(child, ele_href);
                        if (retval)
                            return false;

                    }
                }
            }

            return false;
        }

        private bool FindDimensionChild(PresentationBO presBo, string ele_href)
        {
            if (presBo.Element_Href == ele_href)
            {
                if (presBo.ArcRole == ArcRole.Domain_Member)
                {
                    return true;
                }
            }

            if (presBo.Children != null)
            {
                foreach (PresentationBO child in presBo.Children)
                {
                    bool retVal = FindDimensionChild(child, ele_href);
                    if (retVal)
                        return true;
                }
            }

            return false;
        }


        public object GetObjectFromXsd(string filename)
        {
            object obj = GetObjectFromXsdByFileName(filename, TaxonomyManager.MAINXSD);

            return obj;

        }

        private object GetObjectFromXsdByFileName(string filename, XsdBO xsdBO)
        {
            if (filename == null)
                return null;

            if (TaxonomyManager.MAINXSD.XsdName == filename)
                return TaxonomyManager.MAINXSD;

            foreach (PresentationLinkbaseBO prlbo in TaxonomyManager.MAINXSD.PresLink)
            {
                if (prlbo.LinkBaseName == filename)
                    return prlbo;
            }

            foreach (DefinitonLinkbaseBO dflbo in TaxonomyManager.MAINXSD.DefLink)
            {
                if (dflbo.LinkBaseName == filename)
                    return dflbo;
            }

            foreach (CalculationLinkbaseBO clbo in TaxonomyManager.MAINXSD.CalcLink)
            {
                if (clbo.LinkBaseName == filename)
                    return clbo;
            }

            foreach (LabelLinkbaseBO lbbo in TaxonomyManager.MAINXSD.LabLink)
            {
                if (lbbo.LinkBaseName == filename)
                    return lbbo;
            }

            foreach (XsdBO xsd in TaxonomyManager.MAINXSD.ImportedXsds)
            {
                object obj = GetObjectFromXsdByFileName(filename, xsd);
                if (obj != null)
                    return obj;
            }

            return null;
        }

        public CalculationBO GetCalculationObjectByElHref(string link_ref, string primEl)
        {
            foreach(CalculationLinkbaseBO calLnBo in TaxonomyManager.MAINXSD.CalcLink)
            {
                foreach (CalculationLinkBO calLink in calLnBo.CalculationLinks)
                {
                    if (calLink.Href == link_ref)
                    {
                        foreach (CalculationBO calbo in calLink.Calculations)
                        {
                            CalculationBO calcbo = GetCalculationBo(calbo, primEl);
                            if (calcbo != null)
                                return calcbo;
                        }
                    }
                }
            }

            return null;
        }

        private CalculationBO GetCalculationBo(CalculationBO calbo, string primEl)
        {
            if (calbo.Element_Href == primEl)
                return calbo;

            if (calbo.Children != null)
            {
                foreach (CalculationBO calbo1 in calbo.Children)
                {
                    CalculationBO retval = GetCalculationBo(calbo1, primEl);
                    if (retval != null)
                        return retval;
                }
            }

            return null;
        }

        public HyperCubeBO GetHypercubeBoByHref(string hypercube_ref)
        {
            //assuming hpercube to be present in MAINXSD
            foreach(DefinitonLinkbaseBO defLnBasBo in TaxonomyManager.MAINXSD.DefLink)
            {
                foreach(DefinitionLinkBO defLnBo in defLnBasBo.DefintionLinks)
                {
                    foreach(HyperCubeBO hycBo in defLnBo.HyperCubes)
                    {
                        if(hycBo.Hypercube_Href == hypercube_ref)
                            return hycBo;
                    }
                }
            }

            return null;
        }

        public string GetHypercubeBoParentByHref(string hypercube_ref)
        {
            //assuming hpercube to be present in MAINXSD
            foreach (DefinitonLinkbaseBO defLnBasBo in TaxonomyManager.MAINXSD.DefLink)
            {
                foreach (DefinitionLinkBO defLnBo in defLnBasBo.DefintionLinks)
                {
                    foreach (HyperCubeBO hycBo in defLnBo.HyperCubes)
                    {
                        if (hycBo.Hypercube_Href == hypercube_ref)
                            //return hycBo;
                            return defLnBo.ExtendedLinkRole;
                    }
                }
            }

            return null;
        }

        public ContextElement GetContextElementForHypercubeBoByHref(string hypercube_ref)
        {
            //assuming hpercube to be present in MAINXSD
            foreach (DefinitonLinkbaseBO defLnBasBo in TaxonomyManager.MAINXSD.DefLink)
            {
                foreach (DefinitionLinkBO defLnBo in defLnBasBo.DefintionLinks)
                {
                    foreach (HyperCubeBO hycBo in defLnBo.HyperCubes)
                    {
                        if (hycBo.Hypercube_Href == hypercube_ref)
                            return hycBo.ContextElement;
                    }
                }
            }

            return ContextElement.segment;
        }

        Hashtable m_hstTarget = null;
        public Hashtable GetAllXsdTargetNamespaces()
        {
            m_hstTarget = new Hashtable();

            FillTargetNamespaces(TaxonomyManager.MAINXSD);

            //List<string> keys = new List<string>();
            //foreach (string key in m_hstTarget.Keys)
            //{
            //    keys.Add(key);
            //}

            #region dont do this here
            //check if namespaces are duplicate and add _1,_2 accordingly
            ////for (int idx = 0; idx < m_hstTarget.Count; idx++)
            ////{
            ////    string[] nsSpl = Regex.Split(m_hstTarget[keys[idx]].ToString(), ":::");
            ////    int repeated = 1;
            ////    for (int jdx = idx + 1; jdx < m_hstTarget.Count; jdx++)
            ////    {
            ////        string[] nsSpl1 = Regex.Split(m_hstTarget[keys[jdx]].ToString(), ":::");
            ////        if (nsSpl[0] == nsSpl1[0])
            ////        {
            ////            nsSpl1[0] = nsSpl1[0] + "_" + repeated++;
            ////            m_hstTarget[keys[jdx]] = nsSpl1[0] + ":::" + nsSpl1[1];
            ////        }
            ////    }
            ////}
            //{
            //    m_hstTarget[key] = 1;
            //}
            #endregion

            return m_hstTarget;
        }

        private void FillTargetNamespaces(XsdBO xsdBO)
        {
            //string nsName = xsdBO.XsdName.Substring(0, xsdBO.XsdName.Length - 4);

            if (m_hstTarget[xsdBO.XsdName] == null)
            {
                //m_hstTarget.Add(xsdBO.XsdName, nsName + ":::" + xsdBO.targetNamespace);
                string[] spl = xsdBO.targetNamespace.Split('/');
                m_hstTarget.Add(xsdBO.XsdName, spl[spl.Length-1] + ":::" + xsdBO.targetNamespace);
            }

            if(xsdBO.ImportedXsds != null)
                foreach (XsdBO xsd in xsdBO.ImportedXsds)
                {
                    FillTargetNamespaces(xsd);
                }
        }

        public PresentationBO GetPresentationElement(string link_ref, string element_ref, string order)
        {
            foreach (PresentationLinkbaseBO prLnBas in TaxonomyManager.MAINXSD.PresLink)
            {
                foreach (PresentationLinkBO prLnBo in prLnBas.PresentationLinks)
                {
                    if (prLnBo.Href == link_ref)
                    {
                        foreach(PresentationBO prbo in prLnBo.Presentations)
                        {
                            PresentationBO res = FindPresentationElementRecursive(prbo, element_ref, order);
                            if (res != null)
                                return res;
                        }

                        return null;
                    }
                }
            }

            return null;
        }

        private PresentationBO FindPresentationElementRecursive(PresentationBO prbo, string element_ref, string order)
        {
            if (prbo.Element_Href == element_ref && prbo.Order.ToString() == order)
            {
                return prbo;
            }

            if (prbo.Children != null)
            {
                foreach (PresentationBO prbo1 in prbo.Children)
                {
                    PresentationBO res = FindPresentationElementRecursive(prbo1, element_ref, order);
                    if (res != null)
                        return res;
                }
            }

            return null;
        }

        #region nonreporting nonabstract elements

        public List<string> m_NonRepEls = null;
        public List<string> m_RepEls = null;

        public List<string> FindNonReportedNonAbstractElements(List<string> ReportedElements)
        {
            m_RepEls = ReportedElements;
            m_NonRepEls = new List<string>();
            foreach (PresentationLinkbaseBO prLnBas in TaxonomyManager.MAINXSD.PresLink)
            {
                foreach (PresentationLinkBO prLnBo in prLnBas.PresentationLinks)
                {
                    foreach (PresentationBO prbo in prLnBo.Presentations)
                    {
                        if (prbo.TaxonomyElement != null)
                        {
                            if (!prbo.TaxonomyElement.IsAbstract)
                            {
                                if (!m_RepEls.Contains(prbo.Element_Href))
                                {
                                    m_NonRepEls.Add(prbo.Element_Href);
                                }
                            }
                        }
                        TraversePresentationElementRecursive(prbo);
                    }
                }
            }

            return m_NonRepEls;
        }

        private void TraversePresentationElementRecursive(PresentationBO prbo)
        {
            if (prbo.TaxonomyElement != null)
            {
                if (!prbo.TaxonomyElement.IsAbstract)
                {
                    if (!m_RepEls.Contains(prbo.Element_Href))
                    {
                        m_NonRepEls.Add(prbo.Element_Href);
                    }
                }
            }

            if (prbo.Children != null)
            {
                foreach (PresentationBO prbo1 in prbo.Children)
                {
                    TraversePresentationElementRecursive(prbo1);
                }
            }
        }

        #endregion


        public bool IsHycDimDomPresent(string hyc, string dim, string dom)
        {
            foreach (DefinitonLinkbaseBO defLnBas in TaxonomyManager.MAINXSD.DefLink)
            {
                foreach (DefinitionLinkBO defLnBo in defLnBas.DefintionLinks)
                {
                    foreach (HyperCubeBO hyp in defLnBo.HyperCubes)
                    {
                        if (hyp.Hypercube_Href == hyc)
                        {
                            foreach (HycDimension hycDim in hyp.Dimensions)
                            {
                                if (dim == hycDim.Dimension_Href)
                                {
                                    foreach (HycDomain hycDom in hycDim.Domains)
                                    {
                                        bool isPresent = GetHycDomainRecursive(dom, hycDom);
                                        return isPresent;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return false;

        }

        private bool GetHycDomainRecursive(string dom, HycDomain hycDom)
        {
            if (hycDom.Domain_Href == dom)
                return true;

            if (hycDom.ChildDomains == null)
                return false;

            foreach (HycDomain hycdom1 in hycDom.ChildDomains)
            {
                bool isPresent = GetHycDomainRecursive(dom, hycdom1);
                if (isPresent)
                    return true;
            }

            return false;
        }

        StringBuilder sb1 = new StringBuilder();
        public string CheckDimensionInDefinition()
        {
            sb1 = new StringBuilder();
            foreach (PresentationLinkbaseBO prLnBas in TaxonomyManager.MAINXSD.PresLink)
            {
                foreach (PresentationLinkBO prLnBo in prLnBas.PresentationLinks)
                {
                    foreach (PresentationBO prbo in prLnBo.Presentations)
                    {
                        PresentationElementRecursive(prbo, prLnBo.Href);
                    }
                }
            }

            return sb1.ToString();
        }

        private void PresentationElementRecursive(PresentationBO prbo,string lnHref)
        {
            if (prbo.TaxonomyElement.SubstitutionGroup == XsdSubstitutionGroup.dimensionItem)
            {
                if (!CheckHycDimElementInDefLink(lnHref, prbo.Element_Href))
                    sb1.Append("Dimension: " + prbo.Element_Href + " not present in DefinitionLink: " + lnHref + Environment.NewLine);
            }

            if (prbo.Children != null)
            {
                foreach (PresentationBO prbo1 in prbo.Children)
                {
                    PresentationElementRecursive(prbo1,lnHref);
                }
            }
        }

        public bool CheckHycDimElementInDefLink(string link_ref, string element_ref)
        {
            foreach (DefinitonLinkbaseBO defLnBas in TaxonomyManager.MAINXSD.DefLink)
            {
                foreach (DefinitionLinkBO defLnBo in defLnBas.DefintionLinks)
                {
                    if (defLnBo.Href == link_ref)
                    {
                        foreach (HyperCubeBO hyc in defLnBo.HyperCubes)
                        {
                            HycDimension dim = hyc.Dimensions.Find(p => p.Dimension_Href == element_ref);
                            if (dim != null)
                                return true;
                        }
                        return false;
                    }
                }
            }

            return false;
        }

    }
}
